var phongSkinnedEffectVertexShaderStr = "\
attribute vec3 inPosition;\
attribute vec3 inNormal;\
attribute vec2 inTexCoord0;\
attribute vec4 inMatIdx;\
attribute vec4 inWeight;\
uniform mat4 modelMat;\
uniform mat4 viewProjectionMat;\
uniform mat4 shadowMat;\
uniform vec3 viewPosition;\
uniform mat4 boneMat[24];\
varying vec3 outNormalInWorld;\
varying vec3 outViewVector;\
varying vec2 outTexCoord0;\
varying vec4 shadowCoord;\
void main(void)\
{\
  vec4 netPosition,netNormal ;\
  mat4 combineMat = mat4(0.0);\
  float combineWeight=0.0;\
  for(int i=0;i<4;i++){\
    float idx = inMatIdx[i];\
    combineMat+= (boneMat[int(idx)]*inWeight[i]);\
    combineWeight+=inWeight[i];\
  }\
  mat4 rotateMat = mat4( combineMat[0],combineMat[1],combineMat[2],0,0,0,1);\
  netPosition = combineMat*vec4(inPosition, 1.0)/combineWeight;\
  netNormal =  normalize((rotateMat*vec4(inNormal,1.0)/combineWeight));\
  gl_Position = viewProjectionMat*modelMat*netPosition;\
  shadowCoord = shadowMat*modelMat*netPosition;\
  shadowCoord.z-=0.005;\
  outNormalInWorld = (modelMat* vec4(netNormal.xyz,0.0)).xyz;\
  vec4 posInWorld = modelMat*netPosition;\
  outViewVector = viewPosition - vec3(posInWorld);\
  outTexCoord0 = inTexCoord0;\
}\
";
function gewPhongSkinnedEffect(game)
{
  // General properties
  this.game = game;
  this.gl = game.gl;
  var gl = game.gl;
  this.name = "PhongSkinnedEffect";
  this.scene3d = null;//Current scene3d that using this effect 
  this.materialList = {};
  this.currentPass = null;
   
  // Create Shader
  this.shader = {}; 
  createGLSLShader(gl,this.shader,phongSkinnedEffectVertexShaderStr,phongEffectFragmentShaderStr);
}
gewPhongSkinnedEffect.prototype.destructor = function()
{
  var list  = this.materialList;
  var listLen = list.length;  
  for (var i in list)
  {
    list[i].destructor();
  }
  this.scene3d.removeEffect(this);
},
gewPhongSkinnedEffect.prototype.render = function(scene3d) 
{
  var gl = this.gl; 
  this.scene3d = scene3d;
  var shader = this.shader;
  // push GL state
  // set GL state
  gl.useProgram(shader.program);
  gl.enableVertexAttribArray(shader.inPosition);
  gl.enableVertexAttribArray(shader.inNormal);
  gl.enableVertexAttribArray(shader.inTexCoord0);
  gl.enableVertexAttribArray(shader.inMatIdx);
  gl.enableVertexAttribArray(shader.inWeight);
  gl.enable(gl.DEPTH_TEST);
  gl.enable(gl.CULL_FACE);
  var light = scene3d.mainLight;
  var light_data = light.lightData;
  gl.uniform3f(shader.lightDir,light_data[0],light_data[1],light_data[2]);
  var shadowMat = GEW_SHADOW_BIAS_MAT.mul(light.projectionMat).mul(light.viewMat);
  gl.uniformMatrix4fv(shader.shadowMat, false, shadowMat.data);
  
  var viewProjMat = scene3d.viewProjectMat;
  gl.uniformMatrix4fv(shader.viewProjectionMat, false, viewProjMat.data);
  
  var viewPos = scene3d.viewPosition;
  gl.uniform3f(shader.viewPosition, viewPos.x, viewPos.y, viewPos.z);
  // render pass 0 with all material
  this.currentPass = 0;
  var materialList = this.materialList;
  var listLen = materialList.length;
  for(var i in materialList)
  { 
    materialList[i].render();
  }
  //
  gl.currentPass = null;
  // pop GL state  
  gl.disable(gl.DEPTH_TEST);
  gl.disable(gl.CULL_FACE);
  gl.disableVertexAttribArray(shader.inPosition);
  gl.disableVertexAttribArray(shader.inNormal);
  gl.disableVertexAttribArray(shader.inTexCoord0);
  gl.disableVertexAttribArray(shader.inMatIdx);
  gl.disableVertexAttribArray(shader.inWeight);
}
